﻿using System;
using Autofac;
using WeDonekRpc.Client.Interface;

namespace WeDonekRpc.Client.Ioc
{
    [Attr.ClassLifetimeAttr(Attr.ClassLifetimeType.SingleInstance)]
    internal class IocService : IIocService
    {
        private static Autofac.IContainer _Container = null;
        [ThreadStatic]
        private static IocScope _CurrentScope;

        internal static void Init (IocBuffer buffer)
        {
            _Container = buffer.Build();
        }
        public bool IsRegistered (Type type)
        {
            return _Container.IsRegistered(type);
        }
        public bool IsRegistered (Type type, string name)
        {
            return _Container.IsRegisteredWithKey(name, type);
        }
        public IocScope CreateTempScore ()
        {
            ILifetimeScope lifetime = _Container.BeginLifetimeScope();
            return new IocScope(lifetime);
        }
        public IocScope CreateScore ()
        {
            if (_CurrentScope == null)
            {
                ILifetimeScope lifetime = _Container.BeginLifetimeScope();
                _CurrentScope = new IocScope(lifetime, _Disposable);
                return _CurrentScope;
            }
            else
            {
                return _CurrentScope.CreateScore();
            }
        }
        private static void _Disposable (ILifetimeScope scope)
        {
            _CurrentScope = null;
        }
        public IocScope CreateScore (object key)
        {
            if (_CurrentScope == null)
            {
                ILifetimeScope lifetime = _Container.BeginLifetimeScope(key);
                _CurrentScope = new IocScope(lifetime, _Disposable);
                return _CurrentScope;
            }
            else
            {
                return _CurrentScope.CreateScore(key);
            }
        }
        public object Resolve (Type form)
        {
            if (_CurrentScope == null)
            {
                return _Container.Resolve(form);
            }
            return _CurrentScope.Resolve(form);
        }

        public object Resolve (Type form, string name)
        {
            if (_CurrentScope == null)
            {
                return _Container.ResolveKeyed(name, form);
            }
            return _CurrentScope.Resolve(form, name);
        }

        public T Resolve<T> ()
        {
            if (_CurrentScope != null)
            {
                return _CurrentScope.Resolve<T>();
            }
            return _Container.Resolve<T>();
        }

        public T Resolve<T> (string name)
        {
            if (_CurrentScope != null)
            {
                return _CurrentScope.Resolve<T>(name);
            }
            return _Container.ResolveKeyed<T>(name);
        }

        public bool TryResolve<T> (out T data) where T : class
        {
            if (_CurrentScope != null)
            {
                return _CurrentScope.TryResolve<T>(out data);
            }
            return _Container.TryResolve<T>(out data);
        }

        public bool TryResolve<T> (string name, out T data) where T : class
        {
            if (_CurrentScope != null)
            {
                return _CurrentScope.TryResolve<T>(name, out data);
            }
            return _Container.TryResolveKeyed<T>(name, out data);
        }
    }
}
